/*
 * Logging.cs
 * 
 * Microsoft Office SharePoint Server Managed Protocol Handler
 * 
 * Author: John Kozell (johnkoz@microsoft.com)
 *         Microsoft Coroporation
 * 
 * This code is an adaptation from, and interpretation of, the original SPS 2001 SDK
 * and has been updated with available information at the time of writing.
 * Not all the delcarions and alogrithms have been verified and tested
 * and there is no guarantee that they are accurate or valid, now or in the future.
 * 
 * The .NET Managed COM Interop approach contained herin was NOT created in cooperation
 * with the Microsoft SharePoint product group and has not been officially endorced
 * by Microsoft and therefore is not supported. The user of this code assumes any
 * and all risk with its use and should proceed with discression.
 * 
 * THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 */

using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;


/// <summary>
/// Channels all output for the application.
/// </summary>
internal class Logging
{
	private static int m_ProcessID = 0;
	private static int m_Tab = 0;
	private static TraceSwitch m_TraceLevel = new TraceSwitch("LoggingLevel", "MOSSPH Logging");

	private Logging()
	{
	}


	public static void Initialize()
	{
		if (m_ProcessID == 0)
		{
			Process process = System.Diagnostics.Process.GetCurrentProcess();
			m_ProcessID = process.Id;

			// If asked, we'll initialize with a process specific file name.
			BooleanSwitch tsUniqueLog = new BooleanSwitch("UniqueLog", "Generate separate log for each process instance");
			if (tsUniqueLog.Enabled)
			{
				string strLogFile = string.Format("c:\\{0}-{1:D6}.log",
					process.ProcessName,
					m_ProcessID);

				FileStream logFile = new FileStream(strLogFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
				TextWriterTraceListener myListener = new TextWriterTraceListener(logFile);
				System.Diagnostics.Trace.Listeners.Add(myListener);
				System.Diagnostics.Trace.AutoFlush = true;
			}
		}
	}


	public static void Indent()
	{
		m_Tab++;
	}


	public static void UnIndent()
	{
		m_Tab--;
	}


	public static void Trace(string sMessage)
	{
		Initialize();
		if (m_TraceLevel.Level >= TraceLevel.Verbose)
			Log(sMessage, TraceLevel.Verbose);
	}


	public static void Information(string sMessage)
	{
		Initialize();
		if (m_TraceLevel.Level >= TraceLevel.Info)
			Log(sMessage, TraceLevel.Info);
	}


	public static void Warning(string sMessage)
	{
		Initialize();
		if (m_TraceLevel.Level >= TraceLevel.Warning)
			Log(sMessage, TraceLevel.Warning);
	}


	public static void Error(string sMessage)
	{
		Initialize();
		if (m_TraceLevel.Level >= TraceLevel.Error)
			Log(sMessage, TraceLevel.Error);
	}


	public static void Exception(string sOffendingOperation, Exception e)
	{
		Initialize();
		if (m_TraceLevel.Level >= TraceLevel.Error)
			Log(sOffendingOperation + " [" + e.Message + "]", TraceLevel.Error);
	}


	public static DateTime Start(string message)
	{
		Trace(message + " start");
		return DateTime.Now;
	}


	public static void Stop(string message, DateTime startTime)
	{
		message += " stop";
		if (startTime != DateTime.MinValue)
		{
			TimeSpan ts = new TimeSpan(DateTime.Now.Ticks - startTime.Ticks);
			message += ", duration: " + ts.ToString();
		}
		Trace(message);
	}

	
	public static DateTime Enter(Type type, string method)
	{
		return Enter(type, method, null);
	}


	public static DateTime Enter(Type type, string method, string data)
	{
		string message = type.ToString() + "::" + method + " enter";
		if (data != null && data.Length > 0)
			message += " (" + data + ")";
		Trace(message);

		return DateTime.Now;
	}


	public static void Leave(Type type, string method)
	{
		Leave(type, method, null);
	}
	
			
	public static void Leave(Type type, string method, string data)
	{
		Leave(type, method, data, DateTime.MinValue);
	}
	
	
	public static void Leave(Type type, string method, string data, DateTime enterTime)
	{
		string message = type.ToString() + "::" + method + " leave";
		if (enterTime != DateTime.MinValue)
		{
			TimeSpan ts = new TimeSpan(DateTime.Now.Ticks - enterTime.Ticks);
			message += ", duration: " + ts.ToString();
		}
		if (data != null && data.Length > 0)
			message += ", data: " + data;
		Trace(message);
	}


	public static void Called(Type type, string method)
	{
		Called(type, method, null);
	}

	
	public static void Called(Type type, string method, string data)
	{
		string message = type.ToString() + "::" + method + " called";
		if (data != null && data.Length > 0)
			message += " (" + data + ")";
		Trace(message);
	}


	private static void Log(string str, TraceLevel level)
	{
		if (m_ProcessID != 0)
		{
			string tab = new string(' ', m_Tab * 4);
			string text = string.Format("{0:11}, {1:D6}-{2:D6}, {3}{4}: {5}",
				System.DateTime.Now.ToString(),
				m_ProcessID,
				System.Threading.Thread.CurrentThread.GetHashCode(),
				tab,
				level.ToString(),
				str);

			System.Diagnostics.Trace.WriteLine(text);
		}
	}
}
